package top.zsyle.sycc.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import top.zsyle.sycc.constants.CacheConstant;
import top.zsyle.sycc.domain.CourseType;
import top.zsyle.sycc.exception.GlobalExceptionEnum;
import top.zsyle.sycc.mapper.CourseTypeMapper;
import top.zsyle.sycc.service.ICourseTypeService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import top.zsyle.sycc.utils.AssertUtil;
import top.zsyle.sycc.vo.CourseTypeCrumbsVo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author zhongshiyi
 * @since 2022-12-31
 */
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private Map<String,Object> cache = new ConcurrentHashMap<>();


    /**
     * 课程类型无限级树
     * @return
     */
    @Override
    @Cacheable(cacheNames = CacheConstant.REDIS_COURSE_TYPE_NAME,key = CacheConstant.REDIS_COURSE_TYPE_KEY)
    public List<CourseType> treeData() {
        // 1.从缓存中获取分类树数据
        // Object o = cache.get(CacheConstant.COURSE_TYPE_TREE_DATA_KEY);
//        Object o = redisTemplate.opsForValue().get(CacheConstant.COURSE_TYPE_TREE_DATA_KEY);
//        // 2.判断缓存中是否有分类树数据
//        if (o == null){ // 没有
//            log.info("缓存中不存在，走MySql!");
//            return getTreeData();
//        }else { // 有 服务之间调用，从Redis中获取如果涉及到要强转，那么必须使用JSON进行转换
//            log.info("缓存中存在，走Redis!");
//            List<CourseType> courseTypes = JSON.parseArray(JSONObject.toJSONString(o), CourseType.class);
//            return courseTypes;
//        }
        return getTreeData();
    }

    private List<CourseType> getTreeData() {
        //1.查询全部类型
        List<CourseType> courseTypes = selectList(null);
        //2.什么时候使用map,就是将双重for循环转化为一个map
        //将 list 转化为 map
        Map<Long, CourseType> treeMap = courseTypes.stream().collect(Collectors.toMap(CourseType::getId, courseType -> courseType));
        //3.创建一个新list
        List<CourseType> treeData = new ArrayList<>();
        courseTypes.forEach(c ->{
            if(c.getPid() == null || c.getPid() == 0){
                treeData.add(c);
            }else {
                CourseType courseTypeParent = treeMap.get(c.getPid());
                if (courseTypeParent != null){
                    courseTypeParent.getChildren().add(c);
                }
            }
        });
        // cache.put(CacheConstant.REDIS_COURSE_TYPE_KEY, treeData);
        // redisTemplate.opsForValue().set(CacheConstant.REDIS_COURSE_TYPE_KEY, treeData);
        return treeData;
    }

    /**
     * 面包屑
     * @param courseTypeId
     */
    @Override
    public List<CourseTypeCrumbsVo> crumbs(Long courseTypeId) {
        //1.参数校验
        //2.业务校验
        //2.1该课程类型是否存在
        CourseType type = selectById(courseTypeId);
        AssertUtil.isNotNull(type, GlobalExceptionEnum.ERROR);
        List<CourseType> allList = selectList(null);
        //3.使用split分割该path，并转化为Long集和
        String[] split = type.getPath().split("\\.");
        List<Long> ids = Arrays.stream(split).map(Long::valueOf).collect(Collectors.toList());
        List<CourseType> ownerProductTypes = selectBatchIds(ids);
        List<CourseTypeCrumbsVo> crumbsVoList = new ArrayList<>();
        ownerProductTypes.forEach(e->{
            Wrapper<CourseType> wrapper = new EntityWrapper<>();
            wrapper.eq("pid",e.getPid());
            List<CourseType> courseTypes = selectList(wrapper);
            CourseTypeCrumbsVo courseTypeCrumbsVo = new CourseTypeCrumbsVo(e,courseTypes);
            crumbsVoList.add(courseTypeCrumbsVo);
        });
        return crumbsVoList;
    }


    @Override
    @CacheEvict(cacheNames = CacheConstant.REDIS_COURSE_TYPE_NAME,key = CacheConstant.REDIS_COURSE_TYPE_KEY)
    public boolean deleteById(Serializable id) {
        return super.deleteById(id);
    }

    @Override
    @CacheEvict(cacheNames = CacheConstant.REDIS_COURSE_TYPE_NAME,key = CacheConstant.REDIS_COURSE_TYPE_KEY)
    public boolean updateById(CourseType entity) {
        return super.updateById(entity);
    }

    @Override
    @CacheEvict(cacheNames = CacheConstant.REDIS_COURSE_TYPE_NAME,key = CacheConstant.REDIS_COURSE_TYPE_KEY)
    public boolean insert(CourseType entity) {
        return super.insert(entity);
    }
}
